package cn.netuo.bumbersoll.helper.ble.service;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import cn.netuo.bumbersoll.helper.ble.interf.BluetoothGattWriteCharacteristicsListener;
import lib.grasp.util.L;
import lib.grasp.util.NumberUtil;
import lib.grasp.util.TOAST;
import lib.grasp.util.TimeDateUtil;

/** 连接设备的服务 */
public class BleService extends Service {
	public BluetoothManager mBluetoothManager;
	public BluetoothAdapter mBluetoothAdapter;
	public BluetoothGatt 	mBluetoothGatt;

	public int mConnectionState = STATE_DISCONNECTED;

	public static final int STATE_DISCONNECTED = 0;
	public static final int STATE_CONNECTING = 1;
	public static final int STATE_CONNECTED = 2;

	// 为了传送状态响应状态，要有几条ACTION
	/** 连接成功 */
	public final static String ACTION_GATT_CONNECTED 			= "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
	/** 断开连接 */
	public final static String ACTION_GATT_DISCONNECTED 		= "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
	/** 发现服务 */
	public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
	/** 特征值改变了 */
	public final static String ACTION_DATA_AVAILABLE 			= "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
	/** 读取特征值返回,回调,之后再广播 */
	public final static String ACTION_CHAR_READED 				= "com.example.bluetooth.le.ACTION_CHAR_READED";
	/**  */
	public final static String BATTERY_LEVEL_AVAILABLE 			= "com.example.bluetooth.le.BATTERY_LEVEL_AVAILABLE";
	/**  */
	public final static String EXTRA_DATA 						= "com.example.bluetooth.le.EXTRA_DATA";
	/**  */
	public final static String EXTRA_STRING_DATA 				= "com.example.bluetooth.le.EXTRA_STRING_DATA";
	/**  */
	public final static String EXTRA_DATA_LENGTH 				= "com.example.bluetooth.le.EXTRA_DATA_LENGTH";
	/**  */
	public final static String ACTION_GATT_RSSI 				= "com.example.bluetooth.le.ACTION_GATT_RSSI";
	/**  */
	public final static String EXTRA_DATA_RSSI 					= "com.example.bluetooth.le.ACTION_GATT_RSSI";

	@Override
	public IBinder onBind(Intent intent) {
		L.logOnly(getClass().getName() + "onBind");
		return new LocalBinder();
	}

	/** IBinder代理类, 主要向外暴露Service, 获取Service本身 */
	public class LocalBinder extends Binder {
		public BleService getService() {
			return BleService.this;
		}
	}

	/** 写入结果监听 */
	private BluetoothGattWriteCharacteristicsListener mListener;

	public void setListener(BluetoothGattWriteCharacteristicsListener mListener) {
		this.mListener = mListener;
	}

	/** 连接设备的回调 */
	@SuppressLint("NewApi")
	public BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() {

		/** 与设备的连接状态发生改变 */
		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
			String intentAction;
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				L.logOnly("蓝牙已连接");
				intentAction = ACTION_GATT_CONNECTED;
				mConnectionState = STATE_CONNECTED;
				broadcastUpdate(intentAction);
				gatt.discoverServices();	// 搜索服务
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				L.logOnly("蓝牙已断开");
				mBluetoothGatt = null;
				intentAction = ACTION_GATT_DISCONNECTED;
				mConnectionState = STATE_DISCONNECTED;
				broadcastUpdate(intentAction);
			}
		}

		/** 搜索到了新服务 */
		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
			} else {
				L.logOnly("service is null");
			}
		}

		/** 读取特征值操作回调 */
		@Override
		public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				getCharacteristicValue(characteristic);
			} else {
				L.logOnly("BluetoothGatt Read Failed!");
			}
		}

		/** 写入特征值操作回调 */
		@Override
		public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
			super.onCharacteristicWrite(gatt, characteristic, status);
			broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
			L.logOnly("[特征值写入成功]onCharacteristicWrite - status:" + status);
			if(mListener == null) return;
			mListener.onWrite(gatt, characteristic, status);
		}

		/** 特征值改变了(以通知的形式回调) */
		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//			broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
			L.logOnly("onCharacteristicChanged - status:"); 		// 0成功
		}

		@Override
		public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
			super.onReadRemoteRssi(gatt, rssi, status);
			Intent rssiIntent = new Intent();
			rssiIntent.putExtra(EXTRA_DATA_RSSI, rssi);
			rssiIntent.setAction(ACTION_GATT_RSSI);
			sendBroadcast(rssiIntent);
			if (mBluetoothGatt != null) {
				new Thread(() -> {
					try {
						Thread.sleep(1500);
						mBluetoothGatt.readRemoteRssi();
					} catch (InterruptedException e) {
						L.logOnly(BleService.class.getSimpleName() + e.getMessage());
					}
				}).start();
			}
		}

		@Override
		public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
			super.onDescriptorRead(gatt, descriptor, status);
			L.logOnly("-------------onDescriptorRead");
		}

		// 写入Descript回调
		@Override
		public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
			super.onDescriptorWrite(gatt, descriptor, status);
			L.logOnly("-------------onDescriptorWrite");
		}
	};

	/** 读取特征值操作回调 */
	@SuppressLint("NewApi")
	private void getCharacteristicValue(BluetoothGattCharacteristic characteristic) {
		List<BluetoothGattDescriptor> des = characteristic.getDescriptors();
		Intent mIntent = new Intent(ACTION_CHAR_READED);
		if (des.size() != 0) {
			mIntent.putExtra("desriptor1", des.get(0).getUuid().toString());
			mIntent.putExtra("desriptor2", des.get(1).getUuid().toString());
		}
		mIntent.putExtra("StringValue", characteristic.getStringValue(0));
		String hexValue = NumberUtil.bytesToHex(characteristic.getValue());
		mIntent.putExtra("HexValue", hexValue.toString());
		mIntent.putExtra("time", TimeDateUtil.getDateTimeEs(new Date()));
		sendBroadcast(mIntent);
	}

	/** 蓝牙状态回调,再广播 */
	@SuppressLint("NewApi")
	private void broadcastUpdate(String action, BluetoothGattCharacteristic characteristic) {
		final Intent intent = new Intent();
		intent.setAction(action);
		final byte[] data = characteristic.getValue();
		final String stringData = characteristic.getStringValue(0);
		if (data != null && data.length > 0) {
			final StringBuilder stringBuilder = new StringBuilder(data.length);
			for (byte byteChar : data) {
				stringBuilder.append(String.format("%X", byteChar));
			}
			if (stringData != null) {
				intent.putExtra(EXTRA_STRING_DATA, stringData);
			} else {
				L.logOnly("characteristic.getStringValue is null");
			}

			String 	mNotifyResult 			= stringBuilder.toString();
			String 	mNotifyStringResult 	= stringData;
			int 	mNotifyResultLength 	= data.length;
			intent.setPackage(getPackageName());
			intent.putExtra(EXTRA_DATA			, mNotifyResult);
			intent.putExtra(EXTRA_DATA_LENGTH	, mNotifyResultLength);
		}
		sendBroadcast(intent);
	}

	/** 确认下是否有蓝牙设备 */
	@SuppressLint("NewApi")
	public boolean init() {
		if (mBluetoothManager == null) {
			mBluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
			if (mBluetoothManager == null) {
				TOAST.showShort(this, "未搜索到蓝牙设备");
				return false;
			}
			mBluetoothAdapter = mBluetoothManager.getAdapter();
		}
		if (mBluetoothAdapter == null) {
			TOAST.showShort(this, "未搜索到蓝牙设备");
			return false;
		}
		return true;
	}

	/** 具体连接BLE设备 */
	@SuppressLint("NewApi")
	public boolean connect(String bleAddress) {
		if (mBluetoothAdapter == null || bleAddress == null) {
			TOAST.showShort(this, "蓝牙设备没有初始化或者未指明目标设备");
			return false;
		}

		// 上次连接失败, 或者断开
		if (mBluetoothGatt != null) {
			if (mBluetoothGatt.connect()) {
				mConnectionState = STATE_CONNECTING;
				return true;
			} else return false;
		}

		// 重新开始寻找设备
		final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(bleAddress);
		if (device == null) {
			TOAST.showShort(this, "没有发现蓝牙设备, 请重试");
			return false;
		}
		L.logOnly("连接蓝牙Gatt服务");
		mBluetoothGatt = device.connectGatt(this, true, mBluetoothGattCallback);
		mConnectionState = STATE_CONNECTING;
		return true;
	}

	/** 断开蓝牙Gatt连接 */
	public void disconnect() {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			L.logOnly("蓝牙没有初始化");
			return;
		}
		mBluetoothGatt.disconnect();
	}

	/** 发广播 */
	private void broadcastUpdate(String action) {
		Intent mIntent = new Intent(action);
		sendBroadcast(mIntent);
	}

	/** 断开,关闭Gatt连接 */
	@Override
	public void onDestroy() {
		super.onDestroy();
		close(mBluetoothGatt);
	}

	/** 断开,关闭Gatt连接 */
	@SuppressLint("NewApi")
	public void close(BluetoothGatt gatt) {
		if(gatt != null){
			gatt.disconnect();	// 断开gatt连接
			gatt.close();		// 关闭gatt连接
		}

		if (mBluetoothAdapter != null) {
			mBluetoothAdapter.cancelDiscovery();	// 停止蓝牙扫描
			mBluetoothAdapter = null;
		}
	}
}
